package com.sdy.hospitalguard.embed.keepalive.process;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.sdy.common.utils.Assert;
import com.sdy.common.utils.DateUtil;
import com.sdy.common.utils.StringUtil;
import com.sdy.hospitalguard.biz.model.AccessControlTerminal;
import com.sdy.hospitalguard.biz.model.MatchingPeople;
import com.sdy.hospitalguard.biz.model.RecordOfAccess;
import com.sdy.hospitalguard.biz.model.VisitAppointment;
import com.sdy.hospitalguard.biz.service.AccessControlTerminalService;
import com.sdy.hospitalguard.biz.service.EscortAssociatedService;
import com.sdy.hospitalguard.biz.service.RecordOfAccessService;
import com.sdy.hospitalguard.biz.service.VisitAppointmentService;
import com.sdy.hospitalguard.biz.utils.HttpReqUtil;
import com.sdy.hospitalguard.biz.utils.PdfUtils;
import com.sdy.mvc.utils.JsonUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.List;
import static com.sdy.hospitalguard.biz.constants.UrlConstans.*;

/**
 * <p>
 * 注释
 * </p>
 *
 * @author fb
 * @since 2020/5/20
 */
@Slf4j
@Component
public class DataProcess {

    @Autowired
    private AccessControlTerminalService accessControlTerminalService;
    @Autowired
    private RecordOfAccessService recordOfAccessService;
    @Autowired
    private EscortAssociatedService escortAssociatedService;
    @Autowired
    private VisitAppointmentService visitAppointmentService;

    public void analysis(JSONObject object) {
        String sign = object.getString("DeviceCode");
        // 数据上报时间
        String time = DateUtil.getDate(new Date(object.getLong("Timestamp")*1000), "yyyy-MM-dd HH:mm:ss");
        AccessControlTerminal accessControlTerminal = accessControlTerminalService.getAccess(sign);
        if (accessControlTerminal == null) {
            log.error("未进行门禁卡口设置!");
            log.error("上报数据：{}", object );
        } else {
            RecordOfAccess recordOfAccess = new RecordOfAccess();
            Integer accessId = accessControlTerminal.getId();
            recordOfAccess.setAccessId(accessId);

            Integer libMatInfoNum = object.getInteger("LibMatInfoNum");
            if (libMatInfoNum == 1) {
                JSONArray libMatInfoList = object.getJSONArray("LibMatInfoList");
//                // 人员库ID
//                long libID = libMatInfoList.getJSONObject(0).getLong("LibID");
//                // 库类型
//                long libType = libMatInfoList.getJSONObject(0).getLong("LibType");
                // 匹配状态 1核验成功
                long matchStatus = libMatInfoList.getJSONObject(0).getLong("MatchStatus");
                if (matchStatus == 1) {
                    // 匹配人员ID
                    long matchPersonID = libMatInfoList.getJSONObject(0).getLong("MatchPersonID");
                    recordOfAccess.setUserId(matchPersonID);

                    // 匹配人脸ID
                    long matchFaceID = libMatInfoList.getJSONObject(0).getLong("MatchFaceID");
                    // 匹配人员信息
                    JSONObject matchPersonInfo = libMatInfoList.getJSONObject(0).getJSONObject("MatchPersonInfo");
                    // 姓名
                    String personName = matchPersonInfo.getString("PersonName");
                    // 性别 0未知，1男性，2女性，9未说明
                    long gender = matchPersonInfo.getLong("Gender");
                    // 门禁卡号
                    String cardID = matchPersonInfo.getString("CardID");
                    // 身份证号
                    String identityNo = matchPersonInfo.getString("IdentityNo");

                    // 处理判断识别的方式
                    // 人脸信息数目，范围:[0, 1]
                    Integer faceInfoNum = object.getInteger("FaceInfoNum");
                    // 卡信息数目，范围:[0, 1]
                    Integer cardInfoNum = object.getInteger("CardInfoNum");
                    // 闸机信息数目，范围:[0, 1]
                    Integer gateInfoNum = object.getInteger("GateInfoNum");
                    long collectedTime = 0L;
                    long capSrc = 1L;
                    float temperature = 0.0f;
                    long maskFlag = 0L;
                    if (faceInfoNum == 1) {
                        JSONArray faceInfoList = object.getJSONArray("FaceInfoList");
                        // 采集时间
                        collectedTime = faceInfoList.getJSONObject(0).getLong("Timestamp");
                        // 采集方式 1人脸，2门禁卡，3身份证，4闸机
                        capSrc = faceInfoList.getJSONObject(0).getLong("CapSrc");
                        // 温度
                        temperature = faceInfoList.getJSONObject(0).getFloat("Temperature");
                        // 是否戴口罩，0未知或未启用，1未戴，2戴
                        maskFlag = faceInfoList.getJSONObject(0).getLong("MaskFlag");
//                        // 人脸全景图
//                        JSONObject panoImage = faceInfoList.getJSONObject(0).getJSONObject("PanoImage");
//                        // 人脸小图
//                        JSONObject faceImage = faceInfoList.getJSONObject(0).getJSONObject("FaceImage");
                    }
                    if (cardInfoNum == 1) {
                        JSONArray cardInfoList = object.getJSONArray("CardInfoList");
                        // 采集时间
                        collectedTime = cardInfoList.getJSONObject(0).getLong("Timestamp");
                        // 采集方式 1人脸，2门禁卡，3身份证，4闸机
                        capSrc = cardInfoList.getJSONObject(0).getLong("CapSrc");
                        // 0身份证，1门禁卡
                        long cardType = cardInfoList.getJSONObject(0).getLong("CardType");
                        // 门禁卡字段：物理卡号
                        String cardId = cardInfoList.getJSONObject(0).getString("CardID");
                        // 门禁卡字段：卡状态 1有效，0无效
                        long cardStatus = cardInfoList.getJSONObject(0).getLong("CardStatus");
                        // 身份证字段：物理卡号
                        String name = cardInfoList.getJSONObject(0).getString("Name");
                        // 身份证字段：0未知的性别 1男 2女 9未说明的性别
                        long cardGender = cardInfoList.getJSONObject(0).getLong("Gender");
                        // 身份证字段：民族 01：汉族…
                        long ethnicity = cardInfoList.getJSONObject(0).getLong("Ethnicity");
                        // 身份证字段：出生日期，格式为 YYYYMMDD
                        String birthday = cardInfoList.getJSONObject(0).getString("Birthday");
                        // 身份证字段：住址
                        String residentialAddress = cardInfoList.getJSONObject(0).getString("ResidentialAddress");
                        // 身份证字段：身份证号
                        String cardIdentityNo = cardInfoList.getJSONObject(0).getString("IdentityNo");
                        // 身份证字段：发证机关
                        String issuingAuthority = cardInfoList.getJSONObject(0).getString("IssuingAuthority");
                        // 身份证字段：发证日期，格式为 YYYYMMDD
                        String issuingDate = cardInfoList.getJSONObject(0).getString("IssuingDate");
                        // 身份证字段：证件有效期开始时间，格式为 YYYYMMDD
                        String validDateStart = cardInfoList.getJSONObject(0).getString("ValidDateStart");
                        // 身份证字段：证件有效期结束时间，格式为 YYYYMMDD
                        String validDateEnd = cardInfoList.getJSONObject(0).getString("ValidDateEnd");
                        // 身份证字段：身份证照片IDImage
                        // JSONObject iDImage = cardInfoList.getJSONObject(0).getJSONObject("IDImage");
                    } else if (gateInfoNum == 1) {
                        JSONArray gateInfoList = object.getJSONArray("GateInfoList");
                        // 采集时间
                        collectedTime = gateInfoList.getJSONObject(0).getLong("Timestamp");
                        // 采集方式 1人脸，2门禁卡，3身份证，4闸机
                        capSrc = gateInfoList.getJSONObject(0).getLong("CapSrc");
                        // 进入人员计数
                        long inPersonCnt = gateInfoList.getJSONObject(0).getLong("InPersonCnt");
                        // 进入人员计数
                        long outPersonCnt = gateInfoList.getJSONObject(0).getLong("OutPersonCnt");
                    } else if (faceInfoNum != 1) {
                        log.warn("未找到识别方式，人脸信息数目:{}，卡信息数目:{}，闸机信息数目:{}", faceInfoNum, cardInfoNum, gateInfoNum);
                        return;
                    }

                    Date collectedTimeDate = new Date(collectedTime*1000);
                    // 身份判定
                    List<Integer> type = escortAssociatedService.getVisitId((int)matchPersonID,
                            Integer.parseInt(accessControlTerminalService.getById(accessId).getBuilding()), collectedTimeDate);
                    if (type.size() == 0) {
                        log.error("error,未识别到刷门禁人员的身份!!!");
                        return;
                    }
                    if (type.get(0) == 0) {
                        recordOfAccess.setUserType(0);
                    } else if (type.get(0) == -1) {
                        recordOfAccess.setUserType(1);
                    } else if (type.get(0) == -3) {
                        recordOfAccess.setUserType(3);
                    } else {
                        recordOfAccess.setUserType(2);
                    }
                    recordOfAccess.setCollectedTime(collectedTimeDate);
                    recordOfAccess.setCardState((int)capSrc);
                    // （进和出至少各一个设备）
                    if (accessControlTerminal.getType() == 0) {
                        recordOfAccess.setTurnoverState(0);
                    } else {
                        recordOfAccess.setTurnoverState(1);
                    }
                    recordOfAccess.setPeopleHeat(String.valueOf(temperature));
                    recordOfAccess.setWearMask((int)maskFlag);
                    recordOfAccessService.save(recordOfAccess);
                    // 若为探视还需改变探视表的实际访问时间 ,感觉探视表的实际探视时间没多大意义，识别表已经记录的人员的进出时间记录
                    if (recordOfAccess.getUserType() == 2) {
                        // 执行修改探视表的时间操作
                        for (int i=0; i<type.size(); i++) {
                            if (recordOfAccess.getTurnoverState() == 0) {
                                visitAppointmentService.update(new UpdateWrapper<VisitAppointment>()
                                        .eq("id", type.get(i))
                                        .set("practical_start_time", collectedTimeDate));
                            } else {
                                Integer id = type.get(i);
                                visitAppointmentService.update(new UpdateWrapper<VisitAppointment>()
                                        .eq("id", id)
                                        .set("practical_end_time", collectedTimeDate).set("visit_state", 2));
                                VisitAppointment visitAppointment = visitAppointmentService.getById(id);
                                if (visitAppointment.getPracticalStartTime() == null) {
                                    visitAppointmentService.update(new UpdateWrapper<VisitAppointment>()
                                            .eq("id", id)
                                            .set("practical_start_time", visitAppointment.getVisitStartTime()));
                                }
                            }
                        }
                    }
                } else {
                    log.warn("系统匹配失败：" + transformStatus((int)matchStatus));
                }
            } else {
                log.warn("系统匹配到多个人：" + libMatInfoNum + "。json数据为：{}", object);
            }
        }
    }

    /**
     * 匹配状态转换
     * @param status
     * @return
     */
    private String transformStatus(Integer status) {
        String s = "";
        if (status == 0) {
            s = "无核验状态";
        } else if (status == 1){
            s = "核验成功";
        } else if (status == 2){
            s = "核验失败（比对失败）";
        } else if (status == 3){
            s = "核验失败(比对成功,不在布控时间)";
        } else if (status == 4){
            s = "核验失败(证件已过期)";
        } else if (status == 5){
            s = "强制停止";
        } else if (status == 6){
            s = "非活体";
        } else if (status == 7){
            s = "刷脸开门模式下，刷脸成功";
        } else if (status == 8){
            s = "刷脸开门模式下，刷脸失败";
        } else if (status == 9){
            s = "安全帽识别失败";
        } else if (status == 10){
            s = "核验失败（对比成功，人脸属性异常,与温度和是否戴口罩相关）";
        } else if (status == 11){
            s = "测温异常";
        } else if (status == 21){
            s = "底图录入成功-新增";
        } else if (status == 22){
            s = "底图录入成功-更新";
        } else if (status == 23){
            s = "底图录入成功-人脸采集";
        } else if (status == 24){
            s = "录入失败";
        } else if (status == 25){
            s = "录入失败-证件已过期";
        } else if (status == 26){
            s = "录入失败-非活体";
        } else if (status == 27){
            s = "无效值";
        }
        return s;
    }

    public void addPersonProcess(MatchingPeople matchingPeople) {
        List<AccessControlTerminal> list = accessControlTerminalService.getTerminal(matchingPeople.getBuilding());
        Integer size = list.size();
        try {
            for (int i = 0; i < size; i++) {
                AccessControlTerminal accessControlTerminal = list.get(i);
                // 出去的门禁设备不布控时间
                if (accessControlTerminal.getType() == 1) {
                    matchingPeople.setTimeTemplate(null);
                }
                String ip = accessControlTerminal.getIp();
                Integer library = accessControlTerminal.getLibrary();
                //Assert.isNull(library, "门禁终端未进行初始化配置! 设备ip为:" + ip);
                if (library == null) {
                    log.error("门禁终端未进行初始化配置! 设备ip为:" + ip);
                    log.error("人员信息：{}", matchingPeople);
                    return;
                }
                String url = HTTP + ip + ADD_PERSON.replace("<ID>", library.toString());
                JSONObject request = new JSONObject(true);
                request.put("Num", 1);
                JSONArray personInfoList = new JSONArray();
                JSONObject personInfo = new JSONObject(true);
                personInfo.put("PersonID", matchingPeople.getUserId());
                personInfo.put("LastChange", matchingPeople.getLastChange());
                personInfo.put("PersonCode", matchingPeople.getUserId().toString());
                personInfo.put("PersonName", matchingPeople.getName());
                personInfo.put("Remarks", matchingPeople.getRemark());
                if (StringUtil.isBlank(matchingPeople.getTimeTemplate())) {
                    personInfo.put("TimeTemplateNum", 0);
                    personInfo.put("TimeTemplateList", "[{}]");
                } else {
                    String[] timeArray = matchingPeople.getTimeTemplate().split(",");
                    Integer length = timeArray.length;
                    personInfo.put("TimeTemplateNum", length);
                    JSONArray timeTemplateList = new JSONArray();
                    for (int j = 0; j < length; j++) {
                        JSONObject timeTemplate = new JSONObject(true);
                        timeTemplate.put("BeginTime", timeArray[j].split("-")[0]);
                        timeTemplate.put("EndTime", timeArray[j].split("-")[1]);
                        timeTemplate.put("Index", j);
                        timeTemplateList.add(timeTemplate);
                    }
                    personInfo.put("TimeTemplateList", timeTemplateList);
                }
                JSONArray identificationList = new JSONArray();
                Integer cardSize = 0;
                // 证件类型0:身份证 1:IC 卡99:其他
                if (StringUtil.isBlank(matchingPeople.getCardId()) && StringUtil.isBlank(matchingPeople.getCard())) {
                    cardSize = 0;
                } else if (StringUtil.isNotBlank(matchingPeople.getCardId()) && StringUtil.isNotBlank(matchingPeople.getCard())) {
                    cardSize = 2;
                    JSONObject cardIdJson = new JSONObject(true);
                    cardIdJson.put("Type", 0);
                    cardIdJson.put("Number", matchingPeople.getCardId());
                    identificationList.add(cardIdJson);
                    JSONObject cardJson = new JSONObject(true);
                    cardJson.put("Type", 1);
                    cardJson.put("Number", matchingPeople.getCard());
                    identificationList.add(cardJson);
                } else {
                    cardSize = 1;
                    if (StringUtil.isNotBlank(matchingPeople.getCardId())) {
                        JSONObject cardIdJson = new JSONObject(true);
                        cardIdJson.put("Type", 0);
                        cardIdJson.put("Number", matchingPeople.getCardId());
                        identificationList.add(cardIdJson);
                    } else {
                        JSONObject cardJson = new JSONObject(true);
                        cardJson.put("Type", 1);
                        cardJson.put("Number", matchingPeople.getCard());
                        identificationList.add(cardJson);
                    }
                }
                personInfo.put("IdentificationNum", cardSize);
                personInfo.put("IdentificationList", identificationList);
                String ptohoPath = matchingPeople.getPhotoPath();
                JSONArray imageList = new JSONArray();
                JSONObject image = new JSONObject(true);
                String base64s = "";
                if (StringUtil.isBlank(ptohoPath)) {
                    personInfo.put("ImageNum", 0);
                } else {
                    base64s = PdfUtils.readFileToBase64(ptohoPath);
                    personInfo.put("ImageNum", 1);
                    image.put("FaceID", matchingPeople.getFaceId());
                    image.put("Name", ptohoPath.substring(ptohoPath.lastIndexOf("/")));
                    image.put("Data", base64s);
                    image.put("Size", base64s.length());
                }
                imageList.add(image);
                personInfo.put("ImageList", imageList);
                personInfoList.add(personInfo);
                request.put("PersonInfoList", personInfoList);
                String res = HttpReqUtil.postJson(url, request.toString(), "UTF-8", "UTF-8", 30000, null);
                JSONObject object = JSONObject.parseObject(res);
                JSONObject response = object.getJSONObject("Response");
                if (!(response.getInteger("StatusCode") == 0 && "Succeed".equals(response.getString("StatusString")))) {
                    log.error("人员信息：{}", matchingPeople);
                    return;
                }
                JSONArray array = response.getJSONObject("Data").getJSONArray("PersonList")
                        .getJSONObject(0).getJSONArray("FaceList");
                if (0 == array.getJSONObject(0).getInteger("ResultCode")) {

                } else if (1010 == array.getJSONObject(0).getInteger("ResultCode")) {
                    log.warn("ResultCode:" + array.getJSONObject(0).getInteger("ResultCode") + "导入图片不存在，无法进行人脸识别");
                } else {
                    log.error("ResultCode:" + array.getJSONObject(0).getInteger("ResultCode") +
                            "。userId:" + matchingPeople.getUserId() + "。building:" + matchingPeople.getBuilding());
                    log.error("人员信息：{}", matchingPeople);
                    return;
                }
            }
        } catch (Exception e) {
            log.error("json解析失败", e);
            log.error("人员信息：{}", matchingPeople);
            return;
        }
        log.info("新增成功!");
        return;
    }

    public void deletePersonProcess(String s) {
        // 0为不删除出门门禁设备的数据，1为删除
        Integer type = Integer.parseInt(s.substring(0, 1));
        MatchingPeople matchingPeople = JsonUtil.deserialize(s.substring(1).getBytes(), MatchingPeople.class);
        List<AccessControlTerminal> list = accessControlTerminalService.getTerminal(matchingPeople.getBuilding());
        Integer size = list.size();
        try {
            for (int i = 0; i < size; i++) {
                // 出去的门禁设备不删除人
                AccessControlTerminal accessControlTerminal = list.get(i);
                if (accessControlTerminal.getType() == 1 && type == 0) {

                } else {
                    String ip = accessControlTerminal.getIp();
                    Integer library = accessControlTerminal.getLibrary();
                    if (library == null) {
                        log.error("门禁终端未进行初始化配置! 设备ip为:" + ip);
                        log.error("人员信息：{}", matchingPeople);
                        return;
                    }
                    String url = HTTP + ip + DELETE_PERSON.replace("<PD>", library.toString())
                            .replace("<ID>", matchingPeople.getUserId().toString()).replace("<LastChange>", matchingPeople.getLastChange());
                    String res = HttpReqUtil.delete(url, "UTF-8", 30000, null);
                    JSONObject object = JSONObject.parseObject(res);
                    JSONObject response = object.getJSONObject("Response");
                    if (!(response.getInteger("StatusCode") == 0 && "Succeed".equals(response.getString("StatusString")))) {
                        log.warn("当前终端：{}，无此人PersonID={}", accessControlTerminal.getSign(), matchingPeople.getUserId());
                    }
                }
            }
        } catch (Exception e) {
            log.error("json解析失败", e);
            log.error("人员信息：{}", matchingPeople);
            return;
        }
        log.info("删除成功!");
        return;
    }

}
